/* 
  SZARP: SCADA software 
  

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
/*
 * scc - Szarp Control Center
 * SZARP
 
 *
 * $Id$
 */
#ifndef __SCCTUNNELFRAME_H__
#define __SCCTUNNELFRAME_H__

#include "config.h"

// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <wx/wx.h>
#include <wx/statline.h>
#include <wx/process.h>
#include <wx/txtstrm.h>
#include <wx/tokenzr.h>
#endif

#ifdef new
#undef new
#endif 

#include <vector>

using std::vector;

class SSHConnection;
/**
 * Class resposible for managing and displaying info on support tunnel.
 */
class SCCTunnelFrame : public wxDialog
{
public:
	enum {
		ID_TunnelFrame = wxID_HIGHEST + 200,
		ID_Connect, 
		ID_ConnectBtn,
		ID_CloseBtn,
		ID_Timer,
	};

	SCCTunnelFrame(wxFrame *parent);
	virtual ~SCCTunnelFrame() {};
	DECLARE_EVENT_TABLE();
private:
	/**Handler for event generated by Close button press.
	 * Hides the SCCTunnelFrame, closes the tunnel(if open)*/
	void OnCloseBtn(wxCommandEvent& WXUNUSED(event));

	/**Handler for event generated by Connect button press,
	 * establishes the tunnel*/
	void OnConnectBtn(wxCommandEvent& WXUNUSED(event));

	/**Handler for event generated on SCCTunnelFrame close attempt.
	 * Hides the window and closes the tunnel. Tries to veto the event.
	 * If vetoing is  not possible destroys the window.
	 * @param event event data*/
	void OnClose(wxCloseEvent& event);

	/**Handler for event triggered by timer.
	 * Polls for events from ssh connection*/
	virtual void OnTimer(wxTimerEvent& WXUNUSED(event));

	/**Tries to perform the connection*/
	void Connect();

	/**Deletes connection object ensuring that all events for @see SSHConnection
	 * are processed*/
	void DeleteConnection();

	SSHConnection *connection; 
					/*<pointer to a class wrapping ssh process*/
	wxTextCtrl *user_ctrl;		/*<pointer to TextCtrl containing a user name*/
	wxTextCtrl *password_ctrl;	/*<pointer to TextCtrl containing a user password*/
	wxTextCtrl *port_ctrl;		/*<pointer to TextCtrl containing a port numer*/
	wxTextCtrl *server_ctrl;	/*<pointer to TextCtrl containing a server address*/
	wxTextCtrl *log;		/*<pointer to TextCtrl containing a log of connection status*/
	wxButton *connect_btn;		/*<pointer to Connect button*/
	wxTimer *timer;			/*<timer used for polling ssh prcoess output*/
	wxStatusBar *status_bar;
				/*<frame's status bar widget*/

	/*describes address we will try to connect*/
	struct address {
		wxString addr;			/*<string representing an address*/
		bool valid;			/*<if set to false it means that 
						  we already tried connecting to that address
						  and it failed so we shall no bother trying 
						  it again*/
						  
		address(const wxString& address) : addr(address), valid(true)
		{};
	};
};

class SSHConnection : public wxEvtHandler {
public:
	/**Events correpsondig to states of tunnel connection*/
	enum Event {
		NONE,
		CONNECTION_SUCCES,
		LISTEN_SUCCESS,
		FAILED_TO_LISTEN,
		NETWORK_DOWN,
		NEW_TUN_CONNECTION,
		CLOSED_TUN_CONNECTION,
		PROCESS_KILLED,
		NO_ROUTE_TO_HOST,
		NAME_NOT_KNOWN,
		TEMP_FAILURE_IN_RESOLV,
		AUTH_FAILURE,
		CONNECTION_REFUSED,
		TIMEOUT,
	};

	SSHConnection(const wxString& address, const wxString& username, const wxString& password, long port_no);

	/**Executes the ssh command thus initiating the connection
	 * @return true if ssh command was executed*/
	bool Execute();

	/**Reads stderr of ssh process, if something iteresting
	 * ie. string that is present in @see SSHMessages
	 * is read than return corresponding @see Event
	 * Polling is neccesary because we can not be informed 
	 * asynchronously of data avaiabliity on a stream*/
	Event PollEvent();

	/**Forces connection termination*/
	void Terminate();

	/**Handler for event generated by ssh process termination*/
	virtual void OnTerminate(wxProcessEvent& WXUNUSED(evt));
private:
	/**List of expressions that are written by ssh to stderr which
	 * are of interest for us*/
	static const struct SSHMessage {
		const wxChar* expression;	/*< substring of ssh process output */
		Event event;			/*< event assosciated with this expression*/
	} SSHMessages[];

	/**Command invoking ssh process*/
	wxString command;
	/**Object wrapping ssh process*/
	wxProcess *process;
	/**Pid of a ssh process*/
	int pid;
	/**Latest event*/
	Event event;

	/**Interprets ssh process output by matching it with contents of @see SSHMessages
	 * @param str - line of ssh process output*/
	void InterpretMessage(const wxString& str);
	DECLARE_EVENT_TABLE();
};

#endif 
